package at.fhooe.mc;

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
import at.fhooe.mc.control.ElevatorControlCenter;
import at.fhooe.mc.control.IAdapter;
import at.fhooe.mc.control.automation.IAutomationControl;
import at.fhooe.mc.control.automation.SingleElevatorControlAlgorithm;
import at.fhooe.mc.data.ControlMode;
import at.fhooe.mc.data.DirectionType;
import at.fhooe.mc.data.DoorState;
import at.fhooe.mc.data.ElevatorData;
import at.fhooe.mc.data.FloorData;
import at.fhooe.mc.data.SystemData;
import at.fhooe.mc.data.control.ElevatorControlData;
import at.fhooe.mc.model.ElevatorControlCenterObserver;

public class AutomaticAlgorithmTest
{
	private SingleElevatorControlAlgorithm singleElevatorControlalgorithm;
	private IAutomationControl mockControl;
	private IMocksControl ctrl;
	private SystemData systemData;

	@Before
	public void setUp()
	{
		ctrl = EasyMock.createStrictControl();

		mockControl = ctrl.createMock(IAutomationControl.class);

		singleElevatorControlalgorithm = new SingleElevatorControlAlgorithm();
		systemData = getDefaultSystemData();
	}

	// ==============================================================================
	@Test
	public void testFirstTargetUp() throws Exception
	{
		systemData.getElevators().get(0).setCommittedDirection(DirectionType.UP);
		systemData.getElevators().get(0).setElevatorFloor(0);

		mockControl.autoControl(0, 1);

		ctrl.replay();

		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);

		ctrl.verify();
	}
	// ==============================================================================
	@Test
	public void testFirstTargetDown() throws Exception
	{
		systemData.getElevators().get(0).setCommittedDirection(DirectionType.DOWN);
		systemData.getElevators().get(0).setElevatorFloor(3);

		mockControl.autoControl(0, 2);

		ctrl.replay();

		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);

		ctrl.verify();
	}
	// ==============================================================================
	@Test
	public void testStopEveryFloorUpAndReturnToGround() throws Exception
	{
		systemData.getElevators().get(0).setCommittedDirection(DirectionType.UP);
		systemData.getElevators().get(0).setElevatorFloor(0);

		systemData.getElevators().get(0).getElevatorButton()[1] = true;
		systemData.getElevators().get(0).getElevatorButton()[2] = true;
		systemData.getElevators().get(0).getElevatorButton()[3] = true;


		mockControl.autoControl(0, 1);
		mockControl.autoControl(0, 2);
		mockControl.autoControl(0, 3);

		mockControl.autoControl(0, 0);
		ctrl.replay();

		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		systemData.getElevators().get(0).setElevatorFloor(1);
		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		systemData.getElevators().get(0).setElevatorFloor(2);
		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);

		systemData.getElevators().get(0).setElevatorFloor(3);
		systemData.getElevators().get(0).getElevatorButton()[1] = false;
		systemData.getElevators().get(0).getElevatorButton()[2] = false;
		systemData.getElevators().get(0).getElevatorButton()[3] = false;

		systemData.getFloors().get(0).setFloorButtonDown(false);
		systemData.getFloors().get(1).setFloorButtonDown(false);
		systemData.getFloors().get(2).setFloorButtonDown(false);
		systemData.getFloors().get(3).setFloorButtonDown(false);

		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);

		ctrl.verify();
	}

	//=========================================================================================
	@Test
	public void testStopByFloorButtonUpAndReturnToGround() throws Exception
	{
		systemData.getElevators().get(0).setCommittedDirection(DirectionType.UP);
		systemData.getElevators().get(0).setElevatorFloor(0);

		systemData.getElevators().get(0).getElevatorButton()[0] = false;
		systemData.getElevators().get(0).getElevatorButton()[1] = false;
		systemData.getElevators().get(0).getElevatorButton()[2] = false;
		systemData.getElevators().get(0).getElevatorButton()[3] = false;


		systemData.getFloors().get(0).setFloorButtonDown(true);
		systemData.getFloors().get(1).setFloorButtonDown(true);
		systemData.getFloors().get(2).setFloorButtonDown(true);
		systemData.getFloors().get(3).setFloorButtonDown(true);


		systemData.getFloors().get(0).setFloorButtonUp(false);
		systemData.getFloors().get(1).setFloorButtonUp(false);
		systemData.getFloors().get(2).setFloorButtonUp(false);
		systemData.getFloors().get(3).setFloorButtonUp(false);


		mockControl.autoControl(0, 3);
		mockControl.autoControl(0, 2);
		mockControl.autoControl(0, 1);
		mockControl.autoControl(0, 0);

		ctrl.replay();

		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		systemData.getElevators().get(0).setElevatorFloor(3);
		systemData.getFloors().get(3).setFloorButtonDown(false);
		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		systemData.getElevators().get(0).setElevatorFloor(2);
		systemData.getFloors().get(2).setFloorButtonDown(false);
		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		systemData.getElevators().get(0).setElevatorFloor(1);
		systemData.getFloors().get(1).setFloorButtonDown(false);
		singleElevatorControlalgorithm.newValuesAvailable(systemData, mockControl);
		ctrl.verify();
	}

/*
	// ==============================================================================
	@Test
	public void testNotifyObservers() throws Exception
	{
		mockObserver.updateNewValues(null);

		elevatorControlCenter.registerObserver(mockObserver);

		ctrl.replay();

		elevatorControlCenter.notifyObservers();

		ctrl.verify();
	}

	// ==============================================================================
	@Test
	public void testUnregisterObserver() throws Exception
	{
		elevatorControlCenter.registerObserver(mockObserver);
		elevatorControlCenter.unregisterObserver(mockObserver);

		ctrl.replay();

		elevatorControlCenter.notifyObservers();

		ctrl.verify();
	}
*/
	// ==============================================================================
	private SystemData getDefaultSystemData()
	{
		SystemData defaultData = new SystemData();
		defaultData.setClockTick(1000L);
		defaultData.setFloorHeight(20);

		FloorData f = new FloorData();
		f.setFloorIndex(0);
		f.setFloorButtonDown(false);
		f.setFloorButtonUp(true);
		defaultData.getFloors().add(f);

		f = new FloorData();
		f.setFloorIndex(1);
		f.setFloorButtonDown(true);
		f.setFloorButtonUp(false);
		defaultData.getFloors().add(f);

		f = new FloorData();
		f.setFloorIndex(2);
		f.setFloorButtonDown(true);
		f.setFloorButtonUp(true);
		defaultData.getFloors().add(f);

		f = new FloorData();
		f.setFloorIndex(3);
		f.setFloorButtonDown(false);
		f.setFloorButtonUp(false);
		defaultData.getFloors().add(f);

		ElevatorData defaultElevator = new ElevatorData(4, ControlMode.AUTOMATIC);
		defaultElevator.setElevatorIndex(0);
		defaultElevator.setElevatorFloor(2);
		defaultElevator.setElevatorPosition(10);
		defaultElevator.setCurrentTarget(3);
		defaultElevator.setCommittedDirection(DirectionType.UP);
		defaultElevator.setElevatorDoorStatus(DoorState.OPEN);
		defaultElevator.setElevatorSpeed(23);
		defaultElevator.setElevatorAccel(12);
		defaultElevator.setElevatorCapacity(200);
		defaultElevator.setElevatorWeight(100);

		defaultElevator.getElevatorButton()[0] = false;
		defaultElevator.getElevatorButton()[1] = true;
		defaultElevator.getElevatorButton()[2] = true;
		defaultElevator.getElevatorButton()[3] = false;

		defaultElevator.getServicesFloors()[0] = true;
		defaultElevator.getServicesFloors()[1] = true;
		defaultElevator.getServicesFloors()[2] = true;
		defaultElevator.getServicesFloors()[3] = true;

		defaultData.getElevators().add(defaultElevator);


		return defaultData;
	}

}
